#pragma once

#include "../widgets.h"
#include "basechart_layout.h"
#include "basechart_painter.h"

class BaseChartAbstractPlottable;
class BaseChartCustomPlot;
class BaseChartLegend;
class S_WIDGETS_EXPORT BaseChartAbstractLegendItem
    : public BaseChartLayoutElement {
  Q_OBJECT
  /// \cond INCLUDE_QPROPERTIES
  Q_PROPERTY(BaseChartLegend* parentLegend READ parentLegend)
  Q_PROPERTY(QFont font READ font WRITE setFont)
  Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
  Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont)
  Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE
                 setSelectedTextColor)
  Q_PROPERTY(bool selectable READ selectable WRITE setSelectable NOTIFY
                 selectionChanged)
  Q_PROPERTY(
      bool selected READ selected WRITE setSelected NOTIFY selectableChanged)
  /// \endcond
 public:
  explicit BaseChartAbstractLegendItem(BaseChartLegend* parent);

  // getters:
  BaseChartLegend* parentLegend() const { return mParentLegend; }
  QFont font() const { return mFont; }
  QColor textColor() const { return mTextColor; }
  QFont selectedFont() const { return mSelectedFont; }
  QColor selectedTextColor() const { return mSelectedTextColor; }
  bool selectable() const { return mSelectable; }
  bool selected() const { return mSelected; }

  // setters:
  void setFont(const QFont& font);
  void setTextColor(const QColor& color);
  void setSelectedFont(const QFont& font);
  void setSelectedTextColor(const QColor& color);
  Q_SLOT void setSelectable(bool selectable);
  Q_SLOT void setSelected(bool selected);

  // reimplemented virtual methods:
  virtual double selectTest(const QPointF& pos, bool onlySelectable,
                            QVariant* details = nullptr) const Q_DECL_OVERRIDE;

 signals:
  void selectionChanged(bool selected);
  void selectableChanged(bool selectable);

 protected:
  // property members:
  BaseChartLegend* mParentLegend;
  QFont mFont;
  QColor mTextColor;
  QFont mSelectedFont;
  QColor mSelectedTextColor;
  bool mSelectable, mSelected;

  // reimplemented virtual methods:
  virtual Interaction selectionCategory() const Q_DECL_OVERRIDE;
  virtual void applyDefaultAntialiasingHint(BaseChartPainter* painter) const
      Q_DECL_OVERRIDE;
  virtual QRect clipRect() const Q_DECL_OVERRIDE;
  virtual void draw(BaseChartPainter* painter) Q_DECL_OVERRIDE = 0;
  // events:
  virtual void selectEvent(QMouseEvent* event, bool additive,
                           const QVariant& details,
                           bool* selectionStateChanged) Q_DECL_OVERRIDE;
  virtual void deselectEvent(bool* selectionStateChanged) Q_DECL_OVERRIDE;

 private:
  Q_DISABLE_COPY(BaseChartAbstractLegendItem)

  friend class BaseChartLegend;
};

class BaseChartAbstractPlottable;
class S_WIDGETS_EXPORT BaseChartPlottableLegendItem
    : public BaseChartAbstractLegendItem {
  Q_OBJECT
 public:
  BaseChartPlottableLegendItem(BaseChartLegend* parent,
                               BaseChartAbstractPlottable* plottable);

  // getters:
  BaseChartAbstractPlottable* plottable() { return mPlottable; }

 protected:
  // property members:
  BaseChartAbstractPlottable* mPlottable;

  // reimplemented virtual methods:
  virtual void draw(BaseChartPainter* painter) Q_DECL_OVERRIDE;
  virtual QSize minimumOuterSizeHint() const Q_DECL_OVERRIDE;

  // non-virtual methods:
  QPen getIconBorderPen() const;
  QColor getTextColor() const;
  QFont getFont() const;
};

class S_WIDGETS_EXPORT BaseChartLegend : public BaseChartLayoutGrid {
  Q_OBJECT
  /// \cond INCLUDE_QPROPERTIES
  Q_PROPERTY(QPen borderPen READ borderPen WRITE setBorderPen)
  Q_PROPERTY(QBrush brush READ brush WRITE setBrush)
  Q_PROPERTY(QFont font READ font WRITE setFont)
  Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
  Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
  Q_PROPERTY(int iconTextPadding READ iconTextPadding WRITE setIconTextPadding)
  Q_PROPERTY(QPen iconBorderPen READ iconBorderPen WRITE setIconBorderPen)
  Q_PROPERTY(SelectableParts selectableParts READ selectableParts WRITE
                 setSelectableParts NOTIFY selectionChanged)
  Q_PROPERTY(SelectableParts selectedParts READ selectedParts WRITE
                 setSelectedParts NOTIFY selectableChanged)
  Q_PROPERTY(
      QPen selectedBorderPen READ selectedBorderPen WRITE setSelectedBorderPen)
  Q_PROPERTY(QPen selectedIconBorderPen READ selectedIconBorderPen WRITE
                 setSelectedIconBorderPen)
  Q_PROPERTY(QBrush selectedBrush READ selectedBrush WRITE setSelectedBrush)
  Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont)
  Q_PROPERTY(QColor selectedTextColor READ selectedTextColor WRITE
                 setSelectedTextColor)
  /// \endcond
 public:
  /*!
    Defines the selectable parts of a legend

    \see setSelectedParts, setSelectableParts
  */
  enum SelectablePart {
    spNone = 0x000  ///< <tt>0x000</tt> None
    ,
    spLegendBox = 0x001  ///< <tt>0x001</tt> The legend box (frame)
    ,
    spItems = 0x002  ///< <tt>0x002</tt> Legend items individually (see \ref
                     ///< selectedItems)
  };
  Q_ENUMS(SelectablePart)
  Q_FLAGS(SelectableParts)
  Q_DECLARE_FLAGS(SelectableParts, SelectablePart)

  explicit BaseChartLegend();
  virtual ~BaseChartLegend() Q_DECL_OVERRIDE;

  // getters:
  QPen borderPen() const { return mBorderPen; }
  QBrush brush() const { return mBrush; }
  QFont font() const { return mFont; }
  QColor textColor() const { return mTextColor; }
  QSize iconSize() const { return mIconSize; }
  int iconTextPadding() const { return mIconTextPadding; }
  QPen iconBorderPen() const { return mIconBorderPen; }
  SelectableParts selectableParts() const { return mSelectableParts; }
  SelectableParts selectedParts() const;
  QPen selectedBorderPen() const { return mSelectedBorderPen; }
  QPen selectedIconBorderPen() const { return mSelectedIconBorderPen; }
  QBrush selectedBrush() const { return mSelectedBrush; }
  QFont selectedFont() const { return mSelectedFont; }
  QColor selectedTextColor() const { return mSelectedTextColor; }

  // setters:
  void setBorderPen(const QPen& pen);
  void setBrush(const QBrush& brush);
  void setFont(const QFont& font);
  void setTextColor(const QColor& color);
  void setIconSize(const QSize& size);
  void setIconSize(int width, int height);
  void setIconTextPadding(int padding);
  void setIconBorderPen(const QPen& pen);
  Q_SLOT void setSelectableParts(const SelectableParts& selectableParts);
  Q_SLOT void setSelectedParts(const SelectableParts& selectedParts);
  void setSelectedBorderPen(const QPen& pen);
  void setSelectedIconBorderPen(const QPen& pen);
  void setSelectedBrush(const QBrush& brush);
  void setSelectedFont(const QFont& font);
  void setSelectedTextColor(const QColor& color);

  // reimplemented virtual methods:
  virtual double selectTest(const QPointF& pos, bool onlySelectable,
                            QVariant* details = nullptr) const Q_DECL_OVERRIDE;

  // non-virtual methods:
  BaseChartAbstractLegendItem* item(int index) const;
  BaseChartPlottableLegendItem* itemWithPlottable(
      const BaseChartAbstractPlottable* plottable) const;
  int itemCount() const;
  bool hasItem(BaseChartAbstractLegendItem* item) const;
  bool hasItemWithPlottable(const BaseChartAbstractPlottable* plottable) const;
  bool addItem(BaseChartAbstractLegendItem* item);
  bool removeItem(int index);
  bool removeItem(BaseChartAbstractLegendItem* item);
  void clearItems();
  QList<BaseChartAbstractLegendItem*> selectedItems() const;

 signals:
  void selectionChanged(BaseChartLegend::SelectableParts parts);
  void selectableChanged(BaseChartLegend::SelectableParts parts);

 protected:
  // property members:
  QPen mBorderPen, mIconBorderPen;
  QBrush mBrush;
  QFont mFont;
  QColor mTextColor;
  QSize mIconSize;
  int mIconTextPadding;
  SelectableParts mSelectedParts, mSelectableParts;
  QPen mSelectedBorderPen, mSelectedIconBorderPen;
  QBrush mSelectedBrush;
  QFont mSelectedFont;
  QColor mSelectedTextColor;

  // reimplemented virtual methods:
  virtual void parentPlotInitialized(BaseChartCustomPlot* parentPlot)
      Q_DECL_OVERRIDE;
  virtual Interaction selectionCategory() const Q_DECL_OVERRIDE;
  virtual void applyDefaultAntialiasingHint(BaseChartPainter* painter) const
      Q_DECL_OVERRIDE;
  virtual void draw(BaseChartPainter* painter) Q_DECL_OVERRIDE;
  // events:
  virtual void selectEvent(QMouseEvent* event, bool additive,
                           const QVariant& details,
                           bool* selectionStateChanged) Q_DECL_OVERRIDE;
  virtual void deselectEvent(bool* selectionStateChanged) Q_DECL_OVERRIDE;

  // non-virtual methods:
  QPen getBorderPen() const;
  QBrush getBrush() const;

 private:
  Q_DISABLE_COPY(BaseChartLegend)

  friend class BaseChartCustomPlot;
  friend class BaseChartAbstractLegendItem;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(BaseChartLegend::SelectableParts)

Q_DECLARE_METATYPE(BaseChartLegend::SelectablePart)
